package com.qf.recive;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author 千锋健哥
 */
@Component
@RabbitListener(queues = "queue9")
public class ReciveListener {

    @Autowired
    private RedisTemplate redisTemplate;

    @RabbitHandler
    public void messageHandler(String msg, Channel channel, Message message) throws Exception {
        try {
            //1. 获取消息唯一id
            long id = message.getMessageProperties().getDeliveryTag();

            //2. 使用redis中的setnx方法, 将这个数据存入redis中, 生存时间: 3-5秒
            //第一参数: key, 第二参数: value, 第三参数: 超时时间, 第四参数:时间单位
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(id, "0", 5, TimeUnit.SECONDS);

            //3. 如果能够存入redis, 说明之前没有处理过这个数据, 则执行业务.
            if (flag) {
                System.out.println("======处理业务====");
            }

            //4. 如果不能够存入redis, 说明之前处理过这个数据, 则不执行业务. 直接返回给mq响应, 执行成功
            /**
             * 第一个参数: 消息唯一标识
             * 第二个参数: 是否开启批量处理, 如果开启批量处理, 那么一个消费方处理失败后另一个消费方继续处理.
             */
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            e.printStackTrace();
            //5. 如果有异常, 返回给mq消息, 执行不成功, 从新发送数据
            /**
             * 第一个参数: 消息唯一标识
             * 第二参数: 如果为true, 所有消费者都会拒绝这个消息
             * 第三参数: 如果为true, 消息接收失败后, 消息会从新回到队列,
             *          如果为false那么处理失败后不回队列, 丢弃
             */
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }

    }
}
